﻿//----------------------------------------------------------------
// Copyright (c) 2011-2013 
// All rights reserved.
// Author: Ben DaoWei 
// Contact: bendaowei@gmail.com
// Web Link: http://xnaeditor.codeplex.com
// ----------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MdxLib.Model;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace UnityEngine.Graphics.Shader
{
    public class SystemShader : Shader
    {
        public SystemShader(GraphicsDevice device)
            : base(device)
        {

        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (basicEffect != null)
                    basicEffect.Dispose();

                if (alphaTestEffect != null)
                    alphaTestEffect.Dispose();
            }
            base.Dispose(disposing);
        }

        public override EMaterialLayerFilterMode FliterMode
        {
            set
            {
                BlendState blendState = new BlendState();
                switch (value)
                {
                    case EMaterialLayerFilterMode.Blend:
                        //blendState.ColorSourceBlend = Blend.SourceAlpha;
                        //blendState.ColorDestinationBlend = Blend.InverseSourceAlpha;
                        //blendState.ColorBlendFunction = BlendFunction.Add;

                        //blendState.AlphaSourceBlend = Blend.SourceAlpha;
                        //blendState.AlphaDestinationBlend = Blend.InverseSourceAlpha;
                        //blendState.AlphaBlendFunction = BlendFunction.Add;
                        blendState = BlendState.NonPremultiplied;
                        Effect = BasicEffectInstance;
                        GraphicsDevice.BlendState = blendState;
                        break;
                    case EMaterialLayerFilterMode.Transparent:
                        //blendState.AlphaTestEnable = true;
                        //blendState.AlphaFunction = CompareFunction.Greater;
                        //blendState.ReferenceAlpha = 192;
                        //blendState.AlphaBlendEnable = false;
                        //blendState.SeparateAlphaBlendEnabled = false;
                        AlphaTestEffectInstance.ReferenceAlpha = 192;
                        AlphaTestEffectInstance.AlphaFunction = CompareFunction.Greater;
                        blendState = BlendState.Opaque;
                        Effect = AlphaTestEffectInstance;
                        GraphicsDevice.BlendState = blendState;
                        break;
                    case EMaterialLayerFilterMode.Additive:
                        blendState.AlphaBlendFunction = BlendFunction.Add;
                        blendState.AlphaSourceBlend = Blend.One;
                        blendState.AlphaDestinationBlend = Blend.Zero;

                        blendState.ColorBlendFunction = BlendFunction.Add;
                        blendState.ColorSourceBlend = Blend.One;
                        blendState.ColorDestinationBlend = Blend.Zero;
                        Effect = BasicEffectInstance;
                        GraphicsDevice.BlendState = blendState;
                        break;
                    case EMaterialLayerFilterMode.AdditiveAlpha:
                        blendState.AlphaSourceBlend = Blend.One;
                        blendState.AlphaDestinationBlend = Blend.One;
                        blendState.AlphaBlendFunction = BlendFunction.Add;

                        blendState.ColorSourceBlend = Blend.One;
                        blendState.ColorDestinationBlend = Blend.One;
                        blendState.ColorBlendFunction = BlendFunction.Add;
                        Effect = BasicEffectInstance;
                        GraphicsDevice.BlendState = blendState;
                        break;
                    case EMaterialLayerFilterMode.Modulate:
                        blendState = BlendState.Opaque;
                        Effect = BasicEffectInstance;
                        GraphicsDevice.BlendState = blendState;
                        break;
                    case EMaterialLayerFilterMode.Modulate2x:
                        blendState = BlendState.Opaque;
                        Effect = BasicEffectInstance;
                        GraphicsDevice.BlendState = blendState;
                        break;
                    case EMaterialLayerFilterMode.None:
                        blendState = BlendState.NonPremultiplied;
                        Effect = BasicEffectInstance;
                        GraphicsDevice.BlendState = blendState;
                        break;
                }
            }
        }

        public override Matrix World
        {
            set
            {
                if (Effect as BasicEffect != null)
                    (Effect as BasicEffect).World = value;
                else
                    (Effect as AlphaTestEffect).World = value;
            }
        }

        public override Matrix View
        {
            set
            {
                if (Effect as BasicEffect != null)
                    (Effect as BasicEffect).View = value;
                else
                    (Effect as AlphaTestEffect).View = value;
            }
        }

        public override Matrix Projection
        {
            set
            {
                if (Effect as BasicEffect != null)
                    (Effect as BasicEffect).Projection = value;
                else
                    (Effect as AlphaTestEffect).Projection = value;
            }
        }

        public override Texture2D Texture
        {
            set
            {
                if (Effect as BasicEffect != null)
                    (Effect as BasicEffect).Texture = value;
                else
                    (Effect as AlphaTestEffect).Texture = value;
            }
        }

        public override float Alpha
        {
            set
            {
                if (Effect as BasicEffect != null)
                    (Effect as BasicEffect).Alpha = value;
                else
                    (Effect as AlphaTestEffect).Alpha = value;
            }
        }

        public override bool TextureEnabled
        {
            set
            {
                if (Effect as BasicEffect != null)
                    (Effect as BasicEffect).TextureEnabled = value;
            }
        }


        public BasicEffect BasicEffectInstance
        {
            get
            {
                if (basicEffect == null)
                {
                    basicEffect = new BasicEffect(GraphicsDevice);
                    basicEffect.TextureEnabled = true;
                    //basicEffect.EnableDefaultLighting();

                    GraphicsDevice graphics = basicEffect.GraphicsDevice;

                    graphics.DepthStencilState = DepthStencilState.Default;
                    graphics.BlendState = BlendState.Opaque;
                    graphics.RasterizerState = RasterizerState.CullNone;
                }
                return basicEffect;
            }
        }

        public AlphaTestEffect AlphaTestEffectInstance
        {
            get
            {
                if (alphaTestEffect == null)
                {
                    alphaTestEffect = new AlphaTestEffect(GraphicsDevice);
                    //alphaTestEffect.TextureEnabled = true;
                    //alphaTestEffect.EnableDefaultLighting();
                    GraphicsDevice graphics = alphaTestEffect.GraphicsDevice;

                    graphics.DepthStencilState = DepthStencilState.Default;
                    graphics.BlendState = BlendState.Opaque;
                    graphics.RasterizerState = RasterizerState.CullNone;
                }
                return alphaTestEffect;
            }
        }

        private static BasicEffect basicEffect = null;
        private static AlphaTestEffect alphaTestEffect = null;

        public override void ResetDevice(GraphicsDevice device)
        {
            basicEffect = null;
            alphaTestEffect = null;
            if (device != null)
            {
                GraphicsDevice = device;
            }

            base.ResetDevice(device);
        }

        public override void Render()
        {
            SceneManager.Instance.Render3D();
            base.Render();
        }
    }
}
